import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.swing.DefaultListModel;

class MessageReceiver implements Runnable
{
    SocketChannel client=ChatClientUI.client;

    DefaultListModel listModel=ChatClientUI.listModel;
    
    Map<String, ChatWindow> userChatWindow=ChatClientUI.userChatWindow;

    public MessageReceiver()
    {
        new Thread(this).start();
    }

    public void run()
    {
        String line;
        try
        {
            receiveMessages(client);
        }
        catch (Exception ex)
        {
        }
    }

    public void receiveMessages(SocketChannel client)
    {
        try
        {
            Selector selector = Selector.open();
            client.register(selector, SelectionKey.OP_READ);
            while (true)
            {
                System.out.println("javax.swing.SwingUtilities ############receiveMessages  "
                        + javax.swing.SwingUtilities.isEventDispatchThread());
                System.out.println("before select client");
                selector.select();
                System.out.println("After select client");
                handleSelectedKeys(selector.selectedKeys(), client);
            }
        }
        catch (IOException e)
        {
            System.out.println("Failed to receive message");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    public void handleSelectedKeys(Set selectedkeys, SocketChannel client) throws IOException
    {
        System.out.println("handleSelectedKeys");
        Iterator itr = selectedkeys.iterator();
        while (itr.hasNext())
        {
            SelectionKey key = (SelectionKey) itr.next();
            itr.remove();
            if (key.isReadable())
            {
                System.out.println("isReadable");
                String msgFromServer = readChannel(key, client);
                System.out.println("msgFromServer    " + msgFromServer);
                handleServerMessages(msgFromServer);
            }
        }
    }

    private String readChannel(SelectionKey key, SocketChannel client) throws IOException,
            CharacterCodingException
    {
        int BUFFER_SIZE = 512;
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
        int bytesRead = client.read(buffer);
        buffer.flip();
        Charset charset = Charset.forName("ISO-8859-1");
        CharsetDecoder decoder = charset.newDecoder();
        CharBuffer charBuffer = decoder.decode(buffer);
        String msgFromServer = charBuffer.toString();
        if (bytesRead == -1)
        {
            key.cancel();
            client.close();
        }
        return msgFromServer;
    }

    private void handleServerMessages(String msgFromServer)
    {
        Map<String, String> parameterMap = getParamMap(msgFromServer);
        javax.swing.SwingUtilities.invokeLater(new UiUpdater(parameterMap));
    }

    private Map<String, String> getParamMap(String msgFromServer)
    {
        Map<String, String> parameterMap = null;
        try
        {
            StringTokenizer stringTokens = new StringTokenizer(msgFromServer, "=;");
            parameterMap = new HashMap<String, String>();
            while (stringTokens.hasMoreTokens())
            {
                String key = stringTokens.nextToken();
                String value = stringTokens.nextToken();
                parameterMap.put(key, value);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return parameterMap;
    }
}